package com.hospital.hospitalserver.service;

import com.hospital.hospitalserver.entity.DoctorScheduleRequest;
import com.hospital.hospitalserver.entity.GenerateScheduleRequest;
import com.hospital.hospitalserver.entity.ScheduleDataRequest;
import com.hospital.hospitalserver.entity.ScheduleInstanceDTO;
import com.hospital.hospitalserver.entity.Vo.DoctorSchedule;
import com.hospital.hospitalserver.mapper.ScheduleInstanceMapper;
import com.hospital.hospitalserver.util.Response;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 排班实例实现类
 * */
@Service
@RequiredArgsConstructor
public class ScheduleInstanceService {
    private final ScheduleInstanceMapper scheduleInstanceMapper;

    /**
     * 提交排班实例数据
     * 增加事务管理
     * */
    @Transactional(rollbackFor = Exception.class)
    public Response generateScheduleInstances(GenerateScheduleRequest request){
        List<ScheduleInstanceDTO> instances = request.getInstances();
        String strategy = request.getOverwriteStrategy(); //添加策略

        // 覆盖策略：skip-仅新增, overwrite-覆盖, merge-合并
        switch (strategy) {
            case "skip":
                return handleAddStrategy(instances);
            case "overwrite":
                return handleOverwriteStrategy(instances, request);
            case "merge":
                return handleMergeStrategy(instances);
            default:
                throw new IllegalArgumentException("不支持的覆盖策略: " + strategy);
        }
    }

    /**
     * 仅新增策略：跳过已存在的排班
     */
    private Response handleAddStrategy(List<ScheduleInstanceDTO> instances){
        //过滤已有排班，只添加未班排实例
        List<ScheduleInstanceDTO> filteredInstances = instances.stream().filter(instance ->!checkScheduleExists(instance)).collect(Collectors.toList());
        if(filteredInstances.isEmpty()){
            return Response.success("没有新的排班需要添加");
        }
        if(saveInstancesBatch(filteredInstances)){
            return Response.success("排班实例添加成功");
        }else{
            return Response.error("排班实例添加异常");
        }
    }

    /**
     * 覆盖策略：删除原有排班，插入新排班
     */
    private Response handleOverwriteStrategy(List<ScheduleInstanceDTO> instances,GenerateScheduleRequest request){
        // 1. 获取所有涉及的日期和人员范围
        Set<Integer> staffIds = instances.stream().map(ScheduleInstanceDTO::getStaff_id)
                .collect(Collectors.toSet());
        LocalDate startDate = instances.stream()
                .map(ScheduleInstanceDTO::getSchedule_date)
                .min(LocalDate::compareTo)
                .orElse(LocalDate.now());

        LocalDate endDate = instances.stream()
                .map(ScheduleInstanceDTO::getSchedule_date)
                .max(LocalDate::compareTo)
                .orElse(LocalDate.now());

        // 2. 删除原有排班
        deleteExistingSchedules(staffIds,startDate,endDate);

        // 3. 插入新排班
        if(saveInstancesBatch(instances)){
            return Response.success("添加排班实例成功");
        }else {
            return Response.error("添加排班实例失败");
        }
    }

    /**
     * 合并策略：保留调整过的排班，覆盖正常排班
     */
    private Response handleMergeStrategy(List<ScheduleInstanceDTO> instances){
        List<ScheduleInstanceDTO> instancesToSave = new ArrayList<>();
        //过滤调整过的排班，覆盖正常排班
        for(ScheduleInstanceDTO newInstance : instances){
            ScheduleInstanceDTO existing = findExistingSchedule(newInstance);

            if(existing == null){
                //不存在，直接新增
                scheduleInstanceMapper.addScheduleInstances(newInstance);
            }else{
                // 存在且状态为正常，覆盖更新
                newInstance.setInstance_id(existing.getInstance_id());
                //更新覆盖
                scheduleInstanceMapper.updateScheduleInstances(newInstance);
            }
            // 如果状态不是正常（调班、请假等），则跳过，保留原排班
        }

        if (instancesToSave.isEmpty()) {
            return Response.success("没有需要保存的排班实例");
        }
        if(saveOrUpdateBatch(instancesToSave)){
            return Response.success("更新覆盖成功");
        }
        return Response.error("覆盖更新失败");
    }

    /**
     * 批量保存排班实例
     * */
    private boolean saveInstancesBatch(List<ScheduleInstanceDTO> instances){

        for(ScheduleInstanceDTO instance : instances){
            Integer result = scheduleInstanceMapper.addScheduleInstances(instance);
            if(result==0){
                return false;
            }
        }
        return true;
    }

    /**
     * 删除指定人员和日期范围的排班
     */
    private void deleteExistingSchedules(Set<Integer> staffIds, LocalDate startDate, LocalDate endDate) {
        scheduleInstanceMapper.deleteByStaffAndDateRange(staffIds,startDate,endDate);
    }



    /**
     * 用于覆盖策略
     * 批量保存或更新
     */
    private boolean saveOrUpdateBatch(List<ScheduleInstanceDTO> instances){
        for (ScheduleInstanceDTO instance : instances){
            if(instance.getInstance_id()!=null){
                //更新
                scheduleInstanceMapper.updateScheduleInstances(instance);
            }else {
                //新增
                scheduleInstanceMapper.addScheduleInstances(instance);
            }
        }
        return true;
    }

    /**
     * 检查排班是否已存在
     */
    private boolean checkScheduleExists(ScheduleInstanceDTO instance) {
        return scheduleInstanceMapper.checkExists(instance) > 0;
    }

    /**
     * 查找已存在的排班
     */
    private ScheduleInstanceDTO findExistingSchedule(ScheduleInstanceDTO instance) {
        return scheduleInstanceMapper.findExistingSchedule(instance);
    }

    /**
     * 根据查询条件加载排班实例数据-月视图-周视图-日视图
     * */
    public Response getScheduleInstancesDataBySearch(ScheduleDataRequest request){
        return Response.success(scheduleInstanceMapper.getScheduleInstancesDataBySearch(request));
    }

    /**
     * 获取今天已排班的科室和医生信息
     * 用于挂号
     * */
    public Response getScheduleInstancesDataByCurrentDate(){
        return Response.success(scheduleInstanceMapper.getScheduleInstancesDataByCurrentDate());
    }

    /**
     * 根据科室ID和日期查询医生排班信息
     * */
    public Response selectDoctorByDepartmentAndDate(DoctorScheduleRequest request){
        //日期为空则查询当前
        if(request.getSchedule_date()==null){
            request.setSchedule_date(LocalDate.now().toString());
        }

        if(request.getSchedule_type()==null){
            request.setSchedule_type("outpatient");
        }

        List<DoctorSchedule> doctors = scheduleInstanceMapper
                .selectDoctorByDepartmentAndDate(request.getDepartment_id(),request.getSchedule_date(),request.getSchedule_type());

        return Response.success(doctors);
    }


    /**
     * 根据医生ID查询医生详细信息
     */
    public Response selectDoctorDetailById(DoctorScheduleRequest request){
        return Response.success(scheduleInstanceMapper.selectDoctorDetailById(request.getDoctor_id()));
    }
}
